package com.wanli.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wanli.common.Result;
import com.wanli.domain.entity.Menu;
import com.wanli.domain.entity.Role;
import com.wanli.domain.entity.User;
import com.wanli.domain.vo.TrafficVo;
import com.wanli.mapper.UserMapper;
import com.wanli.service.MenuService;
import com.wanli.service.RoleService;
import com.wanli.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wanli.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Byterain
 * @since 2023-12-06
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    RoleService roleService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private MenuService menuService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public User getUserByUsername(String username) {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.eq("username", username);
        return userMapper.selectOne(qw);
    }

    @Override
    public String getUserAuthorityInfo(Long userId) {
        // 定义权限字符串:
        // 权限字符串格式： 用户具备角色,用户具体权限
        // ROLE_admin,ROLE_normal,sys:user:list,sys:user:save,sys:user:delete.......
        // 权限字符串存储Redis中，键 grantedByterain   值=权限字符串
        //   grantedadmin , 权限字符串
        String authorityString = "";

        // 首先查询该用户的详细信息： 通过userId查询
        User user = this.getById(userId);
        String key = "granted" + user.getUsername();
        // 判断 redis是否已经存在权限字符串。
        if (redisUtil.hasKey(key)) {
            // 如果存在就直接从缓存中获取   以String类型写入redis
            authorityString = (String) redisUtil.get(key);
        } else {
            // Redis中没有这个key,查询数据库，获得权限字符串，写入redis。
            // 查询当前userId这个用户具备哪些角色
            QueryWrapper role_qw = new QueryWrapper();
            // 子查询 select * from sys_role where id in (3,6)
            role_qw.inSql("id", "select role_id from sys_user_role where user_id=" + userId);
            List<Role> roles = roleService.list(role_qw);


            if (roles.size() > 0) {
                // ROLE_admin,ROLE_normal
                String roleString = roles.stream().map(r -> "ROLE_" + r.getCode()).collect(Collectors.joining(","));
                authorityString = roleString + ",";  // 权限字符串中的数据是：ROLE_admin,ROLE_normal,
            }

            // 查询当前用户 所能操作的菜单id
            List<Long> menusIds = userMapper.getNavMenuIds(userId);
            // 根据 菜单一组id，查询该菜单的详细信息
            List<Menu> menus = menuService.listByIds(menusIds);


            if (menus.size() > 0) {
                String perms = menus.stream().map(m -> m.getPerms()).collect(Collectors.joining(",")); // sys:user:list,sys:user:save,sys:user:delete,...
                authorityString = authorityString.concat(perms);
                // 权限字符串  ROLE_admin,ROLE_normal,sys:user:list,sys:user:save,sys:user:delete
                log.info("权限字符串:{}", authorityString);
            }

            // 将获得权限字符串 存储到缓存中
            redisUtil.set(key, authorityString);
        }

        return authorityString;
    }


    // 根据用户名username，删除掉redis中与该用户名相关的权限信息:  用户表-->删除张三-->redis张三权限信息清楚
    @Override
    public void clearUserAuthorityInfo(String username) {
        redisUtil.del("granted" + username);
    }


    @Override
    public void clearUserAuthorityInfoByMenuId(Long menuId) {
        // 查询出 目前和menuId 相关的所有用户
        List<User> users = userMapper.listByMenuId(menuId);
        // 根据查询出来的用户信息，在redis中将这些用户的权限信息进行删除
        users.forEach(u -> {
            this.clearUserAuthorityInfo(u.getUsername());
        });
    }

    @Override
    public void clearUserAuthorityInfoByRoleId(Long roleId) {
        // 找出用户权限和roleId相关的所有的用户
        List<User> users = this.list(new QueryWrapper<User>().inSql("id", "select user_id from sys_user_role where role_id=" + roleId));
        users.forEach(u -> {
            this.clearUserAuthorityInfo(u.getUsername());
        });
    }

    @Override
    public Result getFootTraffic() {
        // 获取当前月份的所有日期集合
        int monthValue = LocalDate.now().getMonthValue();
        int yearValue = LocalDate.now().getYear();

        // 获取当月第一天和最后一天
        LocalDate firstDayOfMonth = YearMonth.of(yearValue, monthValue).atDay(1);
        LocalDate lastDayOfMonth = firstDayOfMonth.with(TemporalAdjusters.lastDayOfMonth());

        // 创建一个日期范围
        List<LocalDate> dateRange = new ArrayList<>();
        for (LocalDate date = firstDayOfMonth; !date.isAfter(lastDayOfMonth); date = date.plusDays(1)) {
            dateRange.add(date);
        }

        // 创建一个 HashMap 来存储日期和对应的访问量
        ArrayList<TrafficVo> dateCount = new ArrayList<>();

        // 从 Redis 中获取每个日期的访问量
        for (LocalDate date : dateRange) {
            String key = date.toString();
            String todayCount = stringRedisTemplate.opsForValue().get(key);
            if (todayCount == null) {
                todayCount = "0"; // 如果没有访问记录，设置为 0
            }

            TrafficVo trafficVo = new TrafficVo(date.format(DateTimeFormatter.ofPattern("MM-dd")), todayCount);
            dateCount.add(trafficVo);
        }

        // 返回结果
        return Result.success(dateCount);
    }


}









